/*
  ArtToSpr Artworks/Draw to Sprite convertor
  Copyright (c) 1998 Tony Houghton

  This source is distributed under the GPL. Please see the file
  "COPYING" for details.
*/

#ifndef __linklist_h
#define __linklist_h

#ifdef __cplusplus
extern "C" {
#endif


/*  Implementation notes
 *  ====================
 *  This module provides support for a linked list structure.
 *  YOU must supply an anchor for the list (a variable of type
 *  linklist_header). This is used to record pointers to the start and end
 *  of the list.
 *  The list itself is made up of your own structures, defined as follows:
 *    struct listelement
 *    {
 *      linklist_header header;
 *      ... Your own data here ...
 *    } listelement;
 *
 *  a list-terminating pointer is represented as NULL
 *
 *  The header's next field stores a pointer to the FIRST item
 *           its previous field stores a pointer to the LAST item
 *           (both these pointers will be nulls if the list is empty)
 *
 *  To insert items into the list, you must malloc memory for one of your
 *  own listelement data structures, then call the appropriate function
 *  To delete an item from the list, call the unlink function, and then free
 *  all memory used by your structure.
 */


typedef struct linklist_header
{
  struct linklist_header *next;
  struct linklist_header *previous;
} linklist_header ;



extern void LinkList_AddToHead(linklist_header *anchor, linklist_header *item);
/*
inserts the given item at the head of the list
*/

extern void LinkList_AddToTail(linklist_header *anchor, linklist_header *item);
/*
inserts the given item at the end of the list
*/

extern void LinkList_InsertBefore(linklist_header *anchor,
                                  linklist_header *pos,
                                  linklist_header *item);
/*
inserts the given item BEFORE the item "pos"
*/

extern void LinkList_InsertAfter(linklist_header *anchor,
                                 linklist_header *pos,
                                 linklist_header *item);
/*
inserts the given item AFTER the item "pos"
*/



extern bool LinkList_InList(linklist_header *anchor, linklist_header *item);
  /*
   *  Returns TRUE if the item is curently in the list. Note that this does
   *  NOT check item contents, merely compares item pointers.
   *  To check item contents, you must chain through the list yourself.
   */


extern int LinkList_ListLength(linklist_header *anchor);
  /*
   *  Returns the number of items in the list. It follows all the links
   *  and counts them... if you need this value a lot, I suggest you modify
   *  LinkList to keep a count in the anchor...
   */



extern void LinkList_Unlink(linklist_header *anchor, linklist_header *item);
  /*
   *  Unlinks the item "item" from the given list.
   *  You must then free the memory used by it yourself.
   */


#define LinkList_FirstItem(x) ((void *)(x)->next)
  /*  Return pointer to the first item in the list
   */

#define LinkList_LastItem(x) ((void *)(x)->previous)
  /*  Return pointer to the last item in the list
   */


#define LinkList_Init(x)  \
  {                       \
    (x)->next = NULL;     \
    (x)->previous = NULL; \
  }
  /*
   *  Initialises a list anchor. Should be called before anchor used
   *    extern void LinkList_Init(linklist_header *item);
   */


#define LinkList_InitItem(x) \
  {                          \
    (x)->next = NULL;        \
    (x)->previous = NULL;    \
  }
  /*
   *  Initialises a list item. Should be called before item used,
   *  except when that item is immediately linked into a list
   *    extern void LinkList_InitItem(linklist_header *item);
   */


#define LinkList_NextItem(x) ((void *) ((linklist_header *)(x))->next)
  /*  Return the next item of a given one. If the current item is at
   *  the tail of the list, NULLPOINTER will be returned.
   *    extern void *LinkList_NextItem(linklist_header *item);
   *
   *  Old definition:
   *    #define LinkList_NextItem(x) ((void *)(x)->next)
   *
   *  NEW definition:
   *    you can now use   LinkList_NextItem(&item);
   *    instead of        LinkList_NextItem(&item->header);
   */


#define LinkList_PreviousItem(x) ((void *) ((linklist_header *)(x))->previous)
  /*  Return the previous item of a given one. If the current item is at
   *  the head of the list, NULLPOINTER will be returned.
   *    extern void *LinkList_PreviousItem(linklist_header *item);
   *
   *  Old definition:
   *    #define LinkList_PreviousItem(x) ((void *)(x)->previous)
   *
   *  NEW definition:
   *    you can now use   LinkList_PreviousItem(&item);
   *    instead of        LinkList_PreviousItem(&item->header);
   */

#ifdef __cplusplus
}
#endif


#endif
